iT邦幫忙

2024 iThome 鐵人賽

DAY 8
0

目標:從 JSON 檔案中取得我的社群媒體資料

我希望保持 NavFooterComponent 元件較小,並將靜態社交媒體簡介封裝在 JSON 檔案中。

  • 新增 social-media.json 來儲存我的 GitHub、Twitter 和 Linkedin 的簡介
  • 產生一個新服務以從 json 檔案檢索我的社交媒體
  • NavFooterComponent 元件注入服務、檢索資料並顯示在 HTML 範本中

將靜態資料儲存在 JSON 檔案中

{
    "github": {
      "href": "https://github.com/railsstudent",
      "text": "Github"
    },
    "twitter": {
      "href": "https://x.com/connieleung404",
      "text": "Twitter"
    },
    "linkedin": {
      "href": "https://www.linkedin.com/in/connieleung107/",
      "text": "Linkedin"
    }
}

新增 /assets/social-media.json 來儲存靜態資料。

產生 SocialMediaService 服務

SocialMediaService 有一個 getProfiles 方法來從 JSON 檔案擷取資料。

import { HttpClient } from '@angular/common/http';
import { inject, Injectable } from '@angular/core';
import { catchError, of, shareReplay } from 'rxjs';
import { SocialMedia } from '../types/social-media.type';

@Injectable({
 providedIn: 'root'
})
export class SocialMediaService {
 http = inject(HttpClient);

 getProfiles() {
   return this.http.get<{ [key: string]: SocialMedia }>('/assets/social-media.json')
     .pipe(
       catchError((err) => {
         console.error(err);
         return of({} as { [key: string]: SocialMedia } );
       }),
       shareReplay(1),
     );
 }
}

HttpClient 檢索 SocialMedia 物件。如果請求導致錯誤,catchError 運算子會捕獲錯誤並傳回一個空物件。 shareReplay 運算子會快取結果,因為資訊不會經常變更。

在 NavFooterComponent 中呼叫 SocialMediaService

import { toSignal } from '@angular/core/rxjs-interop';
import { SocialMediaService } from '../services/social-media.service';

export class NavFooterComponent {
 socialMediaService = inject(SocialMediaService);

 socialMedia = toSignal(
    this.socialMediaService.getProfiles(), 
    { initialValue: {} as { [key: string]: SocialMedia } }
 );
}

getProfiles 方法傳回一個 Observable,我應用 toSignal 函數從中建立一個 signalkeyscomponents computed signals 沒有變化。

imports: [SocialMediaComponent, GithubIconComponent, LinkedinIconComponent, TwitterXIconComponent, NgComponentOutlet],
template: `
       ...
       <div class="flex flex-row basis-1/4">
         @for (key of keys(); track key) {
           <blog-social-media [information]="socialMedia()[key]" class="grow shrink basic-1/3">
             <ng-container *ngComponentOutlet="components()[key]" />
           </blog-social-media>
         }
       </div>
     ...
 `,

範本不會更改,因為它引用相同的 socialMedia signal。

在瀏覽器上導航至 http://localhost:5173/,頁面應保持不變。

Github Repo:


上一篇
Day 7 - 重構導航頁尾元件
下一篇
Day 9 - 使用 ng-content 建立可重複使用的 Card Component
系列文
使用 AnalogJS 建立部落格文章12
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言